%{
   #include "ts.h" /* Contains definition of ‘symrec'. */
   #include <stdio.h>
   #include "y.tab.h" // generado automaticamente por bison, sustituye el antiguo ts.h

   /*enum yytokentype {
   IDENTIFICADOR     = 256,		
   ENTERO            = 257,
   CHAR		     = 258,
   CONST	     = 259,
   INT		     = 265,
   INT1		     = 266,
   INT2		     = 267,
   INT3		     = 268,
   INT4		     = 269,
   INT5		     = 270,
   INT6		     = 271,
   INT7		     = 272,
   INT8		     = 273,
   VOID		     = 274,
   MAIN		     = 280,
   MALLOC	     = 285,
   DELETE	     = 286,
   IF                = 290,
   ELSE              = 291,
   SWITCH            = 295,
   CASE              = 296,
   BREAK             = 297,
   DEFAULT           = 300,
   DO                = 305,
   WHILE             = 306,
   FOR               = 310,
   RETURN	     = 315,
   CONTINUE	     = 316,
   EXIT	    	     = 320,
   PRINTF	     = 325,
   OPASIG            = 330,
   SUMA		     = 331,
   RESTA	     = 332,
   MULTIPLICACION    = 333,
   DIVISION	     = 334,
   MODULO	     = 335,
   SUMA_ASIG	     = 340,
   MULTIPLICA_ASIG   = 341,		
   OPLOG             = 342,
   MEN               = 343,
   MEI               = 344,
   MAY               = 345,		
   MAI               = 346,
   COMP              = 347,
   O_LOG	     = 348,
   Y_LOG	     = 349,
   NOT               = 350,
   DIF               = 351,
   INCREMENTO        = 355,
   DECREMENTO        = 356,
   COMA		     = 360,
   DOS_PUNTOS	     = 361,
   FIN_SENTENCIA     = 362,
   PARENTESIS_ABRE   = 365,
   PARENTESIS_CIERRA = 366,
   CORCHETE_ABRE     = 367,	
   CORCHETE_CIERRA   = 368,
   LLAVE_ABRE        = 369,
   LLAVE_CIERRA      = 370,
   O_BIT	     = 380,
   Y_BIT	     = 381,
   O_ASIGBIT	     = 382,
   Y_ASIGBIT	     = 383,
   COMENTARIO	     = 385,
   CADENA	     = 386

   };
*/
//   float yylval;
   
	/* Tabla de símbolos: Lista de nodos 'nodo_ts' */
//	token *ts;

%}

/* Universal Character Name: the naming conventions for UCS defined by International Standard ISO/IEC 10646 */
UCN     		(\\u[0-9a-fA-F]{4}|\\U[0-9a-fA-F]{8})
obviar         [" " \n\t]+
letra_         [A-Za-z_]
digito         [0-9]
identificador  {letra_}({letra_}|{digito})*
entero         [+-]?{digito}+(\.{digito}*)?(E[+-]?{digito}+)?
real		   entero"."entero
cadena	       L?\"([^"\\]|\\['"?\\abfnrtv]|\\[0-7]{1,3}|\\[Xx][0-9a-fA-F]+|{UCN})*\"
incremento     [++]
decremento     [--]
/* %x commentaario */
comentario    ("/*"([^*]|[\r\n]|(\*+([^*/]|[\r\n])))*"*"+"/")|("//".*)

%%

	/* --------------------------------- */
	/* 	  OPERADORES Y SIGNOS        */
	/* --------------------------------- */
"<="           { return(MEI); }
">"            { return(MAY); }
">="           { return(MAI); }
"<"            { return(MEN); }
"!="           { return(DIF); }
"=="           { return(IGUAL); }
"||"	       { return(O_LOG); }
"&&"	       { return(Y_LOG); }
"|"	       { return(O_BIT); }
"&"	       { return(Y_BIT); }
"->"			{ return(PTR_OP); }
"|="	       { return (O_ASIGBIT); }
"&="	       { return (Y_ASIGBIT); }
"+="	       { return (SUMA_ASIG); }
"-="			{ return(SUB_ASSIGN); }
"*="	       { return (MULTIPLICA_ASIG); }
"/="			{ return(DIV_ASSIGN); }
"%="			{ return(MOD_ASSIGN); }
"^="			{ return(XOR_ASSIGN); }
">>="			{ return(RIGHT_ASSIGN); }
"<<="			{ return(LEFT_ASSIGN); }

"++"           { return INCREMENTO; }
"--"           { return DECREMENTO; }
">>"			{ return(RIGHT_OP); }
"<<"			{ return(LEFT_OP); }
"..."			{ return(ELLIPSIS); }
"!"            { return('!'); }
"="            { return ('='); }
"+"	       { return ('+'); }
"-"	       { return ('-'); }
"*"	       { return ('*'); }
"/"	       { return ('/'); }
"%"	       { return ('%'); }
","	       { return (','); }
":"	       { return (':'); }
";"            { return (';'); }
"("            { return ('('); }
")"            { return (')'); }
"["	       { return ('['); }
"]"	       { return (']'); }
"{"            { return ('{'); }
"}"            { return ('}'); }
"~"			{ return('~'); }
"^"			{ return('^'); }
"?"			{ return('?'); }

	/* --------------------------------- */
	/* 	   PALABRAS RESERVADAS	     */
	/* --------------------------------- */
if             { return(IF);}
else           { return(ELSE);}
switch         { return(SWITCH);}
case           { return(CASE);}
break          { return(BREAK);}
default        { return(DEFAULT);}
do             { return(DO);}
while          { return(WHILE);}
for            { return(FOR);}
return	       { return(RETURN);}
continue       { return(CONTINUE);}
exit	       { return(EXIT);}
char	       { return(CHAR);}
const	       { return(CONST);}
int	           { return(INT);}
int1	       { return(INT1);}
int2	       { return(INT2);}
int3	       { return(INT3);}
int4	       { return(INT4);}
int5	       { return(INT5);}
int6	       { return(INT6);}
int7	       { return(INT7);}
int8	       { return(INT8);}
void	       { return(VOID);}
                                   /* main	       { return(MAIN);} esto tampoco es una palabra reservada (sintacticamente)
                                      malloc	       { return(MALLOC);}
                                      delete	       { return(DELETE);} */
sizeof		{ return(SIZEOF); }
typedef		{ return(TYPEDEF); }
static		{ return(STATIC); }
register		{ return(REGISTER); }
auto			{ return(AUTO); }
extern		{ return(EXTERN); }
float			{ return(FLOAT); }
long			{ return(LONG); }
short			{ return(SHORT); }
signed		{ return(SIGNED); }
unsigned		{ return(UNSIGNED); }
double		{ return(DOUBLE); }
struct		{ return(STRUCT); }
union		{ return(UNION); }
enum			{ return(ENUM); }
volatile			{ return(VOLATILE); }
goto			{ return(GOTO); }


	/* --------------------------------- */
	/* 	      IDENTIFICADORES	     */
	/* --------------------------------- */
{identificador}     { putToken(yytext, IDENTIFICADOR, 0.0); return IDENTIFICADOR; }

	/* --------------------------------- */
	/* 	      LITERALES		     */
	/* --------------------------------- */
{obviar}       { }
{real}         { putToken(yytext, REAL, yylval.doble = atof(yytext)); return REAL; }
{entero}       { putToken(yytext,ENTERO, yylval.entero = atof(yytext)); return ENTERO; }
{cadena}       { putToken(yytext, CADENA, yylval.cadena = atof(yytext)); return CADENA;}
{comentario}   { /*return COMENTARIO;*/ }

%%
/* Tabla de símbolos: Lista de nodos tipo token. */
token *ts;

/*
   Inicialización de la tabla de símbolos:
   1.- Copiado de las palabras reservadas del lenguaje.
*/

void init_table (void) {
   int i;
   token *ptr;

   ptr = putToken("if", IF, 0.0);
   ptr = putToken("else", ELSE, 0.0);
   ptr = putToken("switch", SWITCH, 0.0);
   ptr = putToken("case", CASE, 0.0);
   ptr = putToken("break", DEFAULT, 0.0);
   ptr = putToken("do", DO, 0.0);
   ptr = putToken("while", WHILE, 0.0);
   ptr = putToken("for", FOR, 0.0);
   ptr = putToken("return", RETURN, 0.0);
   ptr = putToken("continue", CONTINUE, 0.0);
   ptr = putToken("exit", EXIT, 0.0);
   ptr = putToken("char", CHAR, 0.0);
   ptr = putToken("const", CONST, 0.0);
   ptr = putToken("int", INT, 0.0);
   ptr = putToken("int1", INT1, 0.0);
   ptr = putToken("int2", INT2, 0.0);
   ptr = putToken("int3", INT3, 0.0);
   ptr = putToken("int4", INT4, 0.0);
   ptr = putToken("int5", INT5, 0.0);
   ptr = putToken("int6", INT6, 0.0);
   ptr = putToken("int7", INT7, 0.0);
   ptr = putToken("int8", INT8, 0.0);
   ptr = putToken("void", VOID, 0.0);
   ptr = putToken("sizeof", SIZEOF, 0.0);
   ptr = putToken("typedef", TYPEDEF, 0.0);
   ptr = putToken("static", STATIC, 0.0);
   ptr = putToken("register", REGISTER, 0.0);
   ptr = putToken("auto", AUTO, 0.0);
   ptr = putToken("extern", EXTERN, 0.0);
   ptr = putToken("float", FLOAT, 0.0);
   ptr = putToken("long", LONG, 0.0);
   ptr = putToken("short", SHORT, 0.0);
   ptr = putToken("signed", SIGNED, 0.0);
   ptr = putToken("unsigned", UNSIGNED, 0.0);
   ptr = putToken("double", DOUBLE, 0.0);
   ptr = putToken("struct", STRUCT, 0.0);
   ptr = putToken("union", UNION, 0.0);
   ptr = putToken("enum", ENUM, 0.0);
   ptr = putToken("volatile", VOLATILE, 0.0);
   ptr = putToken("goto", GOTO, 0.0);

}

token * putToken (char const *name, int type, double value) {
   token *ptr;
   ptr = (token *) malloc (sizeof (token));

   ptr->nombre = (char *) malloc (strlen (name) + 1);
   strcpy (ptr->nombre, name);
   ptr->tipo = type;
   ptr->valor.numero = value;

   ptr->next = (struct token *) ts;
   ts = ptr;
   return ptr;
}

token * getToken (char const *name) {
   token *ptr;
   for (ptr = ts; ptr != (token *) 0; ptr = (token *)ptr->next)
      if (strcmp (ptr->nombre, name) == 0)
         return ptr;
   return 0;
}

void deleteTS() {
   token *ptr;

   while(ts != (token *) 0) {
      ptr = ts->next;
      free(ts);
      ts = ptr;
   }
}

void showTS() {
   token *ptr = ts;

   printf("\nTokens almacenados en la tabla de símbolos:\n");

   while(ptr != (token *) 0) {
      if (ptr->tipo == IF) {
         printf("<IF>");
      } else
      if (ptr->tipo == ELSE) {
         printf("<ELSE>");
      } else
      if (ptr->tipo == IDENTIFICADOR) {
         printf("<IDENTIFICADOR,%s>",ptr->nombre);
      } else {
         printf("name %s, type %d value %g",ptr->nombre, ptr->tipo, ptr->valor.numero);
      }
      ptr = ptr->next;
      printf("\n");
   }
   printf("\n");
}
int main(int argc, char **argv) {
   int tok;

   if(argc > 1) {
      if(!(yyin = fopen(argv[1], "r"))) {
         printf("ERROR: El archivo de entrada no pudo ser leído.\n");
         exit(0);
      }
   }

//FILE * yyout;
//   if(argc == 2) {
//      if(!(yyout = fopen(argv[2], "w"))) {
//         printf("ERROR: El archivo de salida no pudo ser leído.\n");
//         exit(0);
//      }
//   }

   init_table ();

   if (yyparse()) {
       printf ("yyparse: 1 \n");
      }

//   fclose(yyout);

   return 0;
}
